package td.pt.widget;

import java.util.Comparator;
import java.util.Date;

import td.client.place.NameTokens;
import td.domain.Thinker;
import td.domain.Thought;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.ProvidesKey;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.PopupViewImpl;

public class ReferenceListingPopupView extends PopupViewImpl implements
		ReferenceListingPopupPresenter.MyView {

	private final Widget widget;

	public interface Binder extends UiBinder<Widget, ReferenceListingPopupView> {
	}

	/**
	 * The main DataGrid.
	 */
	@UiField(provided = true)
	CellTable<Thought> cellTable;

	/**
	 * The pager used to change the range of data.
	 */
	@UiField(provided = true)
	SimplePager pager;

	@UiField
	Button useReference;

	@UiField
	Button copyReference;

	@UiField
	Button close;

	@UiField
	Label title;

	MultiSelectionModel<Thought> selectionModel;

	Column<Thought, Boolean> checkColumn = new Column<Thought, Boolean>(
			new CheckboxCell(true, false) {

			}) {
		@Override
		public Boolean getValue(Thought object) {
			return selectionModel.isSelected(object);
		}

	};

	Column<Thought, Hyperlink> titleColumn = new Column<Thought, Hyperlink>(
			new AbstractCell<Hyperlink>() {

				@Override
				public void render(
						com.google.gwt.cell.client.Cell.Context context,
						Hyperlink value, SafeHtmlBuilder sb) {
					sb.append(SafeHtmlUtils.fromTrustedString(value.toString()));
				}
			}) {
		@Override
		public Hyperlink getValue(Thought thought) {
			String text = thought.getTitle();
			String targetHistoryToken = NameTokens.detail + ";name="
					+ thought.getId();
			return new Hyperlink(text, targetHistoryToken);
		}
	};

	Column<Thought, Hyperlink> thinkerColumn = new Column<Thought, Hyperlink>(
			new AbstractCell<Hyperlink>() {

				@Override
				public void render(
						com.google.gwt.cell.client.Cell.Context context,
						Hyperlink value, SafeHtmlBuilder sb) {
					sb.append(SafeHtmlUtils.fromTrustedString(value.toString()));
				}
			}) {
		@Override
		public Hyperlink getValue(Thought thought) {
			Thinker thinker = thought.getThinker();
			String text = thought.getThinker().getThinkerId();
			String targetHistoryToken = NameTokens.thinker + ";name="
					+ thinker.getId();
			return new Hyperlink(text, targetHistoryToken);
		}
	};

	Column<Thought, Date> publishedDateColumn = new Column<Thought, Date>(
			new AbstractCell<Date>() {

				@Override
				public void render(
						com.google.gwt.cell.client.Cell.Context context,
						Date value, SafeHtmlBuilder sb) {
					sb.appendEscaped(value.toString());
				}
			}) {
		@Override
		public Date getValue(Thought thought) {
			return thought.getPublishedDate();
		}
	};

	public static final ProvidesKey<Thought> KEY_PROVIDER = new ProvidesKey<Thought>() {
		@Override
		public Object getKey(Thought item) {
			return item == null ? null : item.getId();
		}
	};

	private ListDataProvider<Thought> dataProvider = new ListDataProvider<Thought>();

	@Inject
	public ReferenceListingPopupView(final EventBus eventBus,
			final Binder binder) {
		super(eventBus);

		cellTable = new CellTable<Thought>(KEY_PROVIDER);
		cellTable.setWidth("100%", true);
		cellTable.setSelectionModel(selectionModel);

		selectionModel = new MultiSelectionModel<Thought>(KEY_PROVIDER);
		cellTable.setSelectionModel(selectionModel,
				DefaultSelectionEventManager.<Thought> createCheckboxManager());

		ListHandler<Thought> sortHandler = new ListHandler<Thought>(
				dataProvider.getList());
		cellTable.addColumnSortHandler(sortHandler);

		pager = new SimplePager(TextLocation.CENTER);
		pager.setDisplay(cellTable);
		dataProvider.addDataDisplay(cellTable);

		initTableColumns(cellTable, sortHandler);

		widget = binder.createAndBindUi(this);
	}

	/**
	 * Add the columns to the table.
	 */
	private void initTableColumns(CellTable<Thought> cellTable,
			ListHandler<Thought> sortHandler) {

		cellTable.addColumn(checkColumn,
				SafeHtmlUtils.fromSafeConstant("<br/>"));
		cellTable.setColumnWidth(checkColumn, 40, Unit.PX);

		titleColumn.setSortable(true);
		sortHandler.setComparator(titleColumn, new Comparator<Thought>() {
			@Override
			public int compare(Thought o1, Thought o2) {
				return o1.getTitle().compareTo(o2.getTitle());
			}
		});
		cellTable.addColumn(titleColumn, "Title");
		cellTable.setColumnWidth(thinkerColumn, 55, Unit.PCT);

		thinkerColumn.setSortable(true);
		sortHandler.setComparator(thinkerColumn, new Comparator<Thought>() {
			@Override
			public int compare(Thought o1, Thought o2) {
				return o1.getThinker().getThinkerId()
						.compareTo(o2.getThinker().getThinkerId());
			}
		});
		cellTable.addColumn(thinkerColumn, "Thinker");
		cellTable.setColumnWidth(thinkerColumn, 15, Unit.PCT);

		publishedDateColumn.setSortable(true);
		sortHandler.setComparator(publishedDateColumn,
				new Comparator<Thought>() {
					@Override
					public int compare(Thought o1, Thought o2) {
						return o1.getPublishedDate().compareTo(
								o2.getPublishedDate());
					}
				});
		cellTable.addColumn(publishedDateColumn, "Published");
		cellTable.setColumnWidth(publishedDateColumn, 30, Unit.PCT);
	}

	@Override
	public Widget asWidget() {
		return widget;
	}

	public CellTable<Thought> getCellTable() {
		return cellTable;
	}

	public SimplePager getPager() {
		return pager;
	}

	public Button getUseReference() {
		return useReference;
	}

	public Button getCopyReference() {
		return copyReference;
	}

	public Button getClose() {
		return close;
	}

	public MultiSelectionModel<Thought> getSelectionModel() {
		return selectionModel;
	}

	public void refresh() {
		dataProvider.refresh();
	}

	public Label getTitle() {
		return title;
	}

	public ListDataProvider<Thought> getDataProvider() {
		return dataProvider;
	}

}
